<?php

/**
 * 计数器限流 用string实现
 * Class CounterLimit
 */
class CounterLimitString
{
    // 限制最多跑多少次
    const LIMIT_COUNT = 100;
    // 多少时间间隔
    const LIMIT_UNIT = 60;
    // REDIS Hash的键
    const LIMIT_KEY = 'limit:counter:';
    const LIMIT_TIME_KEY = 'limit:time:';
    // 过期时间
    const TTL = 120;

    // Redis 实例
    private $redis;

    public function __construct()
    {
        $this->redis = new Redis();
        $this->redis->connect('127.0.0.1', 6379);
    }

    /**
     * 检测请求是否可以通过
     *
     * @param $uid
     * @return bool
     */
    public function checkRequest($uid)
    {
        $timeKey = self::LIMIT_TIME_KEY . $uid;
        // 得到上次请求的时间
        $lastTime = $this->redis->get($timeKey);
        if ($lastTime) {
            // 这个有记录时间戳哦
            // 看看时间戳是不是已经过了一分钟(自己设定的时间范围)
            $nowTime = time();
            if ($nowTime - $lastTime < self::LIMIT_UNIT) {
                // 还没一分钟
                // 获取下请求了多少次
                $countKey = self::LIMIT_KEY . $lastTime . ':' . $uid;
                $count = $this->redis->get($countKey);
                if ($count >= self::LIMIT_COUNT) {
                    // 超过次数了
                    return false;
                } else {
                    // 没超过加一
                    $this->redis->set($countKey, ++$count, self::TTL);
                }

            } else {
                // 超过一分钟了可以重置了
                $this->initLimitData($uid);
            }

        } else {
            // 都没有记录肯定没请求或好久没请求了 可以重置了
            $this->initLimitData($uid);
        }
        return true;
    }

    /**
     * 重置限制数据
     *
     * @param $uid
     * @return bool
     */
    private function initLimitData($uid)
    {
        $time = time();
        $timeKey = self::LIMIT_TIME_KEY . $uid;
        $this->redis->set($timeKey, $time, self::TTL);
        $countKey = self::LIMIT_KEY . $time . ':' . $uid;
        $this->redis->set($countKey,1,self::TTL);
        return true;
    }


}
